<?php
if (!defined('INSIDE')) {die('Hacking attempt');}
/**
 * PhTemplate
 * 
 * This package is distributed under the
 * GNU General Public License v.3.
 * See the LICENSE.txt file for details.
 * 
 * @package   Phlame
 * @author    Phlegma <phlegma@pheelgood.net>
 * @copyright 2008 by Phlegma, Phlame
 * @link 	  http://ugamela-forum.pheelgood.net
 * @since     11.06.2008
 * @version   0.1
 * @access    public
 * 
 * Last modify: 12.06.2008
 */

// thx to Ralf Geschke @kuerbis.org for his class KTemplate. I reused some code.

class PhTemplate
{
	const TEMPLATEFILE_NOT_FOUND_OR_NOT_READABLE = 'Could not find or read the templatefile';
	const PASSED_PARAM_TYPE_NOT_STRING = 'Passed param type is not string';

	protected $_delims = array( 'before' => '{', 'after' => '}');
	/**
     * Template text
     * @var      string
     */
	protected $_template;

	/**
     * Parsed templates in an Array
     * Saves parsed templates
     * @var      array
     */
	protected $_parsed_templates = array();

	/**
     * This array contains the assigned strings or objects.
     * @var      array
     */
	protected $_vars = array();

	/**
     * Array of template objects and their contents.
     * @var     array
     */
	protected $_blocks = array();

	/**
     * Name of template file
     * @var     string
     */
	protected $_templatefile;

	/**
     * Name of class, taken from get_class() function.
     * @var    string
     */
	protected $_className;


	/**
	 * Creates a new templateobject
	 * loads a template by the given filename
	 *
	 * @param string $templatefilename
	 */
	public function __construct($templatefilename = '')
	{
		$this->_className = get_class($this);
		$this->loadTemplateFile($templatefilename);
	}

	/**
     * Submit a string variable as template content.
     * This is useful if your template doesn't exist as file,
     * e.g. if it is saved in a database.
     * 
     * @param    string $templatestring
     * @access   public
     * @return   void
     */
	public function loadTemplateContent($templatestring="")
	{
		$this->_parsed_templates[] = $this->_template = $templatestring;
		$this->_initTemplate();
	}

	/**
     * Load and initialize template file.
     * This is only useful if it is not possible to 
     * set a template filename by creating an instance of
     * the template class.
     * 
     * @param    string $filename  Name of template file.
     * @access   public
     * @return   void
     */	
	public function loadTemplateFile($filename = "")
	{
		if (!$filename)
		return false;
		if ($filename)
		$this->_templatefile = $filename;
		if (!file_exists($this->_templatefile) || !is_readable($this->_templatefile))
		{
			throw new Exception(self::TEMPLATEFILE_NOT_FOUND_OR_NOT_READABLE);
		}
		$this->_parsed_templates[] = $this->_template = file_get_contents($this->_templatefile); // faster as fopen+fread+.. management
		$this->_initTemplate();
	}

	/**
     * Parse the template.
     * This function creates the template object tree and replaces contents
     * of blocks with simple placeholders. 
     * 
     * @return   void
     */
	protected function _initTemplate()
	{
		preg_match_all("/<!--\s+BEGIN\s+([A-Za-z0-9\-_]*?)\s+-->(.*)<!--\s+END\s+(\\1)\s+-->/ms",$this->_template,$ma,PREG_PATTERN_ORDER);
		foreach ($ma[1] as $index => $blockname)
		{
			$this->_blocks[$blockname] = new $this->_className('');
			$this->_blocks[$blockname]->loadTemplateContent($ma[2][$index]);

		}
		$this->_template = preg_replace("/<!--\s+BEGIN\s+([A-Za-z0-9\-_]*?)\s+-->(.*)<!--\s+END\s+(\\1)\s+-->\s*/ms",$this->_delims['before'].'\1'.$this->_delims['after'],$this->_template);
		/*for ($i = 0; $i < count($ma[0]); $i++)
		{
		$search = "/\s*\n*<!--\s+BEGIN\s+(" . $ma[1][$i] . ")?\s+-->(.*)<!--\s+END\s+(" . $ma[1][$i]. ")\s+-->\s*\n*              /ms";
		$replace = $this->_delimiterStart . $ma[1][$i] . $this->_delimiterEnd;

		$this->_bl[$ma[1][$i]] = new $this->_className('');
		$this->_bl[$ma[1][$i]]->loadTemplateContent($ma[2][$i]);
		$this->_template = preg_replace($search,$replace,$this->_template);
		}*/
	}

	/**
     * Delete the contents of submitted variables.
     * 
     * @param    none
     * @access   public
     * @return   void
     */
	public function flush()
	{
		//unset($this->_pl);
		$this->_vars = array();
	}

	/**
     * Fetch a block out of the template.
     * If the block exists, this function returns a Template object,
     * otherwise nothing (false).
     * When parsing the template, the blocks will removed
     * into Template objects and replaced with placeholders. 
     * The name of the placeholder is identical to the name 
     * of the removed block.
     * 
     * @param    string $blockName
     * @access   public
     * @return   Template or boolean false
     * @magic
     */
	protected function __get($value)
	{
		if (isset($this->_blocks[$value]))
		{
			return $this->_blocks[$value];
		}
		else
		{
			return false;
		}
	}

	/**
     * Add value to a placeholder.
     * If the placeholder doesnt exist, it will be created.
     * 
     * The parameter $varName can be a string 
     * or a Template object with get() method. 
     * 
     * @param    mixed $varName
     *           Allowed types:    Requirements:
     *           string            $varValue
     *           object            Template object or any object which
     *                             returns HTML code via get() method.
     *
     * @param    string or object $varValue
     * @access   public
     * @magic 
     */
	protected function __set($varName,$varValue)
	{
		if (!is_string($varValue) && !is_object($varValue))
		{
			throw new ErrorException(self::PASSED_PARAM_TYPE_NOT_STRING);
		}
		if (!isset($this->_vars[$varName]))
		{
			$this->_vars[$varName] = '';
		}
		$this->_vars[$varName] .= is_object($varValue) ?  $varValue->get() :  $varValue;
		/*if (is_object($varValue))
		{
		$this->_vars[$varName] .= $varValue->get();
		}
		else
		{
		$this->_vars[$varName] .= $varValue;
		}*/
	}

	/**
     * Assign more than one value to placeholders
     *
     * @param array $vars [ array("name_of_the_placeholder" => Value, ..) ]
     * @return void
     */
	public function massVarSet(array $vars)
	{
		foreach ($vars as $key => $value)
		{
			if (!isset($this->_vars[$key]))
			{
				$this->_vars[$key] = '';
			}
			$this->_vars[$key] .= is_object($value) ?  $value->get() :  $value;
		}
		array_merge($this->_vars,$vars);
	}

	/**
	 * Changes the delimeters of the placeholders
	 *
	 * @param string $before
	 * @param string $after
	 * @return void
	 */
	public function change_delims($before,$after)
	{
		$this->_delims['before'] = (string) $before;
		$this->_delims['after'] = (string) $after;
	}

	/**
     * Print a template with all replacements done.
     * 
     * @param    none
     * @access   public
     */
	public function output()
	{
		print $this->parsetemplate();
	}

	/**
     * Calls parsetemplate(). Returns a template with all replacements done. 
     * 
     * @param    none
     * @access   public
     * @return   string parsed template content
     */
	public function get()
	{
		return $this->parsetemplate();
	}
	
	public function getParsedTemplates()
	{
		return $this->_parsed_templates;
	}
	/**
     * Returns a template with all replacements done. 
     *
     * This new function works without destruction of the
     * template string.
     * 
     * @param    none
     * @access   public
     * @return   string parsed template content
     */
	public function parsetemplate()
	{
		//$t = $this->_template;
		if (isset($this->_vars) && is_array($this->_vars))
		{
			$this->_parsed_templates[] = $t = preg_replace('#'.$this->_delims['before'].'([a-z0-9\-_]*?)'.$this->_delims['after'].'#Ssie', '( ( isset($this->_vars[\'\1\']) ) ? $this->_vars[\'\1\'] : \'\' );', $this->_template);
		}
		/*foreach ($this->_vars as $key => $value)
		{
		$search = $this->_delimiterStart . $key . $this->_delimiterEnd;
		$replaceText = "";
		for ($i = 0; $i < count($this->_pl[$key]); $i++)
		{
		if (is_object($this->_pl[$key][$i]))
		$replaceText .= $this->_pl[$key][$i]->get();
		else
		$replaceText .= $this->_pl[$key][$i];
		}
		$t = str_replace($search,$replaceText,$t);
		}
		}*/
		return $t;
	}
}

?>